<template>
  <div id="container"></div>
</template>

<script setup>
import * as THREE from "three";
import { onMounted } from "vue";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import dat from 'dat.gui'

// 创建控制对象
const controlData = {
  intensity: 0,
  intensityVisable: false,
  light: 0,
  lightVisable: false
}

// 创建实例
const gui = new dat.GUI()
const f = gui.addFolder('配置')

f.add(controlData, "intensityVisable").onChange(function (val) {
  // console.log(val, 'val')
  controlData.intensity = val ? 1 : 0
}).name('添加环境光')

f.add(controlData, "lightVisable").onChange(function (val) {
  // console.log(val, 'val')
  controlData.light = val ? 100 : 0
}).name('点光源')
// 光源的强度
f.add(controlData, "intensity").min(0).max(10).step(1).name('环境光源强度')
// 光源的功率
f.add(controlData, "light").min(0).max(200).step(10).name('点光源强度')


f.domElement.id = "gui"

f.open()


// 创建场景
// 场景能够让你在什么地方、摆放什么东西来交给three.js来渲染，这是你放置物体、灯光和摄像机的地方。
const scene = new THREE.Scene();
// 添加背景颜色
scene.background = new THREE.Color(0x666666);

// 创建相机
const camera = new THREE.PerspectiveCamera();
camera.position.y = 3;
camera.position.z = 10;

// 创建立方体
const geometry = new THREE.BoxGeometry(1, 1, 1)

// 创建lambert反射材质
// const material = new THREE.MeshLambertMaterial({
//   color: 0x00ff00,
// })

const material = new THREE.MeshPhongMaterial({
  color: 0x0099ff,
  shininess: 1000
})

// 创建mesh
const cube = new THREE.Mesh(geometry, material)
cube.position.set(0, 0.5, 0)
// 箱子去接受光源
cube.receiveShadow = true;
// 箱子去投射光源
cube.castShadow = true;
scene.add(cube)

// 添加灯光
// 添加环境光
var ambient = new THREE.AmbientLight(0xffffff, 1);
scene.add(ambient); //将环境光添加到场景中
// console.log(ambient)
// 添加点光源
const light = new THREE.PointLight( 0xffffff, 100, 100)
light.position.set(5, 3, 5)
light.castShadow = true;
// console.log(light)
scene.add(light)
// 添加灯光辅助对象
const sphereSize = 0.1;
const pointLightHelper = new THREE.PointLightHelper( light, sphereSize );
scene.add( pointLightHelper );

// const directionalLight = new THREE.DirectionalLight( 0xffffff, 10)
// directionalLight.position.set(5, 3, 5)
// directionalLight.castShadow = true;

// scene.add(directionalLight)


// 添加坐标辅助线
const axesHelper = new THREE.AxesHelper( 5 );
scene.add( axesHelper );

// 创建地面
const meshfloor = new THREE.Mesh(
  new THREE.PlaneGeometry(10, 10),
  new THREE.MeshPhongMaterial({ 
    color:  0x1B5E20
  })
)
// rotation 单位欧拉角  三维物体（Object3D）
meshfloor.rotation.x -= Math.PI / 2;
// 地面同样设置去接受光源
meshfloor.receiveShadow = true;
scene.add(meshfloor);

onMounted(() => {
  // 创建渲染器
  const renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.shadowMap.enabled = true;
  // renderer.shadowMap.type = THREE.BasicShadowMap; // default THREE.PCFShadowMap 
  // 将gui添加到页面
  document.getElementById('container').appendChild(f.domElement)
  // 将渲染器添加到页面
  document.getElementById("container").appendChild(renderer.domElement);

  // 添加轨道控制器
  const controls = new OrbitControls(camera, renderer.domElement);

  // 让立方体动起来
  function animate() {
    // 告诉浏览器——你希望执行一个动画，并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数，该回调函数会在浏览器下一次重绘之前执行。
    requestAnimationFrame(animate);
    ambient.intensity = controlData.intensity
    light.intensity = controlData.light
    // 轨道控制器更新
    controls.update();
    renderer.render(scene, camera);
  }
  animate();
});
</script>
<style>
  #container .btns{
    position: absolute;
    top: 0
  }
  #gui {
    position: absolute;
    right: 0;
    width: 300px;
  }
</style>